package string.leetcode.medium;

import java.util.HashMap;
import java.util.Map;

/**
 * @author bruin_du
 * @description 把字符串转换成整数
 * @date 2022/6/16 22:37
 **/
public class Offer67_StrToInt {
    public int strToInt(String str) {
        //方法一，简单易懂
        method1(str);

        //方法二：状态机
        //这里不推荐，学一下怎么用
        return method2(str);
    }

    private int method1(String str) {
        char[] arr = str.toCharArray();
        if (arr.length == 0) {
            return 0;
        }
        int sign = 1, res = 0, i = 0;
        int max = Integer.MAX_VALUE / 10;
        while (i < arr.length && arr[i] == ' ') i++;
        if(i == arr.length) return 0;
        if (arr[i] == '-') {
            sign = -1;
            i++;
        } else if (arr[i] == '+'){
            i++;
        }
        for (int j = i; j < arr.length; j++) {
            if (!Character.isDigit(arr[j])) {
                break;
            } else {
                if (res > max || (res == max && arr[j] > '7')) {
                    return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
                }
                res = res * 10 + arr[j] - '0';
            }
        }
        return sign * res;
    }

    private int method2(String str) {
        AutoMaton autoMaton = new AutoMaton();
        for (int i = 0; i < str.length() && autoMaton.flag; i++) {
            autoMaton.get(str.charAt(i));
        }
        return (int) (autoMaton.sign * autoMaton.res);
    }

    public static void main(String[] args) {
        Offer67_StrToInt o = new Offer67_StrToInt();
        o.method2("4193 with words");
    }
}

class AutoMaton {
    public int sign = 1;
    public long res = 0;
    public boolean flag = true;
    private int state = 1;
    private Map<Integer, Integer[]> map = new HashMap<Integer, Integer[]>() {{
        put(1, new Integer[]{1, 2, 3, 4});
        put(2, new Integer[]{4, 4, 3, 4});
        put(3, new Integer[]{4, 4, 3, 4});
        put(4, new Integer[]{4, 4, 4, 4});
    }};

    public void get(char ch) {
        state = map.get(state)[getIndex(ch) - 1];
        if (state == 2 && ch == '-') {
            sign = -1;
        } else if (state == 3) {
            res = res * 10 + ch - '0';
            if (res > Integer.MAX_VALUE) {
                res = sign == 1 ? (long) Integer.MAX_VALUE : -(long) Integer.MIN_VALUE;
                flag = false;
            }
        } else if (state == 4) {
            flag = false;
        }
    }

    private int getIndex(char ch) {
        if (ch == ' ') {
            return 1;
        } else if (ch == '-' || ch == '+') {
            return 2;
        } else if (ch >= '0' && ch <= '9') {
            return 3;
        } else {
            return 4;
        }
    }
}
